#! c:\Python27\python.exe

import thread
import threading
from MySocket import MySocket
import socket
import Tkinter
import tkMessageBox
import tkSimpleDialog
from Tkinter import *
from collections import deque

from config import config

class ClientStub():
	def __init__(self, conn, addr, id):
		self.conn = conn
		self.addr = addr
		self.id = id
		self.event = threading.Event()
		self.event.clear()
		self.quiting = False
		self.msgQueue = deque()
		self.lock = threading.Lock()
		thread.start_new_thread(self.run, () )
		
	def run(self):
		while True:
			self.event.wait()
			
			if (self.quiting):
				break
			
			self.lock.acquire()
			item = None
			if (len(self.msgQueue) > 0):
				item = self.msgQueue.popleft()
				
			if (item == None):
				self.event.clear()
				
			self.lock.release()
			
			if item != None:
				MySocket.sendObject(self.conn, item)
				
		
		self.conn.close()
		
	def pushmessage(self, pack):
		self.lock.acquire()
		self.msgQueue.append(pack)
		self.event.set()
		self.lock.release()
		
				
	def scheduleExit(self):
		self.quiting = True
	
class ChatServer():
	def addStub(self, stub):
		self.lock.acquire()
		self.stublist.append(stub)
		self.lock.release()
		
	def removeStub(self, stub):
		stub.scheduleExit()
		
		self.lock.acquire()
		self.stublist.remove(stub)
		self.lock.release()
		
	def broadcast(self, message, id):
		self.lock.acquire()
		for stub in self.stublist:
			stub.pushmessage(["message", message, id])
		self.lock.release()
	
	def clientHandler(self, conn, addr, id):
		print "handling connection from %s" % (repr(addr))
		stub = ClientStub(conn, addr, id)
		self.addStub(stub)
		
		stub.pushmessage(["clientID", id])
		
		while True:
			try:
				data = MySocket.recvObject(conn)
				if (len(data) < 1):
					continue
				cmd = data[0]
				print 'Get command %s from %s' % (cmd, id)
				if cmd == 'broadcast':
					if (len(data) < 2):
						print 'warning: client package missing argument'
						continue
					message = data[1]
					self.broadcast(message, id)
					continue
				if cmd == 'quit':
					break
				print 'unrecognized command'
			except Exception as inst:
				print 'catch exception of client %s (%s), disconnecting' % (id, addr)
				print type(inst)
				print inst.args
				break
		
		self.removeStub(stub)

	def __init__(self):
		self.s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
		self.s.bind(('127.0.0.1', config["ChatServerPort"]))
		self.s.listen(4)	
		
		self.lock = threading.Lock()
		self.stublist = []
		while True:
			conn, addr = self.s.accept()
			addr = repr(addr)
			thread.start_new_thread(self.clientHandler, (conn, addr, addr) )
			

if __name__ == '__main__':
	chatserver = ChatServer()